﻿using System;
using System.Runtime.InteropServices;

namespace EastFantasy.EasyEngine.Public
{
    public class Win32
    {
        #region win32 api

        public struct MemoryBasicInformation
        {
            public int BaseAddress;
            public int AllocationBase;
            public int AllocationProtect;
            public int RegionSize;
            public int State;
            public int Protect;
            public int lType;
        }

        public const int MEM_COMMIT = 0x1000; //已物理分配
        public const int MEM_PRIVATE = 0x20000;
        public const int PAGE_READWRITE = 0x04; //可读写内存

        [DllImport("kernel32.dll", EntryPoint = "OpenProcess")] //调用动态链接库openprocess方法
        public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll")] //查询内存块信息
        public static extern int VirtualQueryEx(
            IntPtr hProcess, IntPtr lpAddress, out MemoryBasicInformation lpBuffer, int dwLength);

        [DllImport("kernel32.dll")]
        public static extern bool ReadProcessMemory(
            IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int size, out int numBytesRead);

        [DllImport("kernel32.dll")]
        public static extern bool WriteProcessMemory(
            IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int size, out int numBytesWrite);

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        private struct TokPriv1Luid
        {
            public int Count;
            public long Luid;
            public int Attr;
        }

        [DllImport("kernel32.dll", ExactSpelling = true)]
        private static extern IntPtr GetCurrentProcess();

        [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);

        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

        [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
                                                         ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern bool ExitWindowsEx(int flg, int rea);

        [DllImport("kernel32", EntryPoint = "CloseHandle")]
        private static extern int CloseHandle(int hObject);

        #endregion

        #region

        private const string SE_DEBUG_NAME = "SeDebugPrivilege";
        private const int SE_PRIVILEGE_ENABLED = 0x00000002;
        internal const int TOKEN_QUERY = 0x00000008;
        internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;

        public static bool EnableDebugPrivilege(bool bEnable, IntPtr handle)
        {
            bool fOK = false;
            IntPtr hToken = IntPtr.Zero;
            //handle = GetCurrentProcess();
            fOK = OpenProcessToken(handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref hToken)
                ; //打开进程访问令牌

            //试图修改“调试”特权
            TokPriv1Luid tp = new TokPriv1Luid();
            tp.Count = 1;
            tp.Luid = 0;
            tp.Attr = SE_PRIVILEGE_ENABLED;
            fOK = LookupPrivilegeValue(null, SE_DEBUG_NAME, ref tp.Luid);
            tp.Attr = bEnable ? SE_PRIVILEGE_ENABLED : 0;
            fOK = AdjustTokenPrivileges(hToken, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
            //fOK = (GetLastError() == ERROR_SUCCESS);
            CloseHandle(hToken.ToInt32());

            return fOK;
        }

        #endregion
    }
}